Written by Steve Scherrer - July/August 2021

Background

This notebook documents preliminary analysis of tracking data for fish tagged in Molokini Crater between 2020-05-16 and 2021-05-24.

The purpose of this study is to understand how human impacts affect the fish of Molokini Crater

We are particularly interested in answering the following hypotheses: 1. Is the presence of fish affected by vessel presence

  1. Does the proportion of time fish are present within the crater negatively correlated with vessel presence?

Proposed Approach: 1. Begin by calculating the number of each species tagged and basic summary statistics 2. Calculate Metrics - Receiver Use - Pianka’s Niche Overlap - residency 3. Make the following plots - Map - Receiver locations - Map - Average receiver use by Species - Scatterplot - day night plots - Bar Plot - The number of detections per day (individual) - Bar Plot - The number of individuals detected (species) - Line Chart - The proportion of individuals detected n days after tagging (30 day moving average by species) - Bar Plot - Daily vessel traffic - Scatter Plot - vessel traffic vs. proportion of fish detected in crater daily (scatterplot by species) 4. Perform the following statistical Tests - Compare Residency Rates by Species - Compare residency by species, size, and time at liberty - Create a GLM comparing # of individuals in crater regressed against boat traffic and species using AR(1) term on dependent variable on some time scale (daily? 6 hours? depends on resolution of vessel data)

Workspace Setup

Establish Directory Heirarchy

project_directory = '/Users/stephenscherrer/Documents/Programming/Projects/Molokini'
scripts_directory = file.path(project_directory, 'Analysis Scripts')
data_directory = file.path(project_directory, 'Data')
results_directory = file.path(project_directory, 'Results')
figure_directory = file.path(results_directory, 'Figures')

Source package dependencies and utility functions from ‘Utility Functions.R’ file

source(file.path(scripts_directory, 'Utility Functions.R'))

Load Data

  • load various datafiles
## Files from VUE 
molo_df = load_vemco_data(file.path(data_directory, 'VUE_Export.csv'))
false_detections_df = load_fdf_report(file.path(data_directory, 'FDA.csv'))

## Vessel Traffic data
vessel_df = 

## Metadata Files
tagging_df = load_tagging_data(file.path(data_directory, ))
## temp 
tagging_df = data.frame(tag_id = detections_per_tag_per_receiver$tag_id, species = sample(c('a', 'b', 'c'), size = nrow(detections_per_tag_per_receiver), replace = T))

receiver_df = load_receiver_data(file.path(data_directory, ))

Clean Data

  • Associate detections with time of day (day, night, dawn, dusk)
  • Remove detections from tags not associated with this study
  • Remove false detections
## Associate detections with time of day
molo_df = get_time_of_day(molo_df)

## Remove irrelevant tags
# molo_df = molo_df[molo_df$full_tag_id %in% tagging_df$vem_tag_id, ]

## Filter false detections
molo_df = filter_false_detections(molo_df)

Exploratory Data Analysis

Count of individuals tagged by species

tags_by_species = aggregate(tag_id ~ species, data = tagging_df, FUN = uniqueN)
  colnames(tags_by_species) = c('species', 'n_tagged')
print(tags_by_species)

Summary Statistics

# Time at liberty
time_at_liberty = calculate_time_at_liberty(molo_df)

# Days Detected
days_detected = calculate_days_detected(molo_df)

# % of days detected
detection_stats = merge(x = days_detected, y = time_at_liberty[ ,c('tag_id', 'days_at_liberty')], on.x = 'tag_id', on.y = 'tag_id')
detection_stats$percent_days_detected = round(detection_stats$unique_days / detection_stats$days_at_liberty, 4) * 100

# Merge with tagging data to get fish info
detection_stats = merge(x = tagging_df[ ,c('tagging_datetime', 'species', 'tag_id', 'fork_length_cm', )], y = detection_stats, on.x = 'tag_id', on.y = 'tag_id')
detection_stats = detection_stats[ ,order(detection_stats$species, detection_stats$tagging_datetime, detection_stats$tag_id)]
print(detection_stats)

Metric Calculations

index of receiver use

Calculate Pianka’s Niche Overlap Index - Pianka (1973) The Structure of Lizard Communities

0 = no overlap, 1 = perfect overlap

Plots

Study Area

Species Use Plots

## Make species plots for receiver use
for(species in species_receiver_use$species){
  receiver_use_by_spp = ggmap(molo_basemap) + 
    geom_point(data = species_receiver_use[species_receiver_use$species == species, ], 
               mapping = aes(x = lon, y = lat, color = 'red', size =  receiver_use)) + 
    labs(x = '°Longitude', y = '°Latitude') +
    ggsave(filename = paste('Receiver Use by ', species, '.pdf', sep = ''), path = figure_directory)
  print(receiver_use_by_spp)
}
Saving 7 x 7 in image

Day Night Plots

### Day Night Plots
## For all fish
plot_day_night(molo_df, plot_title = 'All Fish')

## By Species
for (spp in unique(tagging_df$species)){
  plot_day_night(molo_df[molo_df$tag_id == tagging_df$tag_id[tagging_df$species == spp], ], plot_title = spp)
}

## By Individual
for (tag_id in molo_df$tag_id){
  plot_day_night(molo_df[molo_df$tag_id == tag_id, ], plot_title = paste(tagging_df$species[tagging_df$tag_id == tag_id], '- Tag', as.character(tag_id), sep = ' '))
}

Barplot of detections by date

ggplot(data = detections_per_day_df, mapping = aes_string(x = 'date', y = column)) +
  geom_bar(stat = "identity") + labs(title = paste('Tag ', strsplit(x = column, split = '_')[[1]][2], sep = ''), x = 'Date', y = 'Detections') + ggsave(filename = paste('Daily Detection Barplot -', column, '.pdf'), path = figure_directory)
Saving 7 x 7 in image

Bar plot # of Fish (standardized percent of fish tagged to date) by date and Spp

## Convert detections_per_day to presence/absence
presence_absence_wide_df = detections_per_day_df
for (i in 2:ncol(presence_absence_wide_df)){
  presence_absence_wide_df[ ,i] = as.numeric(presence_absence_wide_df[ ,i] > 0)
}

## Convert from wide to long format
presence_absence_long_df = melt(presence_absence_wide_df, id.vars = c('date'), measure.vars = colnames(presence_absence_wide_df)[2:ncol(presence_absence_wide_df)], variable.name = 'tag_id', value.name = 'detected')

# Drop 'tag_' prefix from tag_id column for matching purposes
presence_absence_long_df$tag_id = levels(presence_absence_long_df$tag_id)[presence_absence_long_df$tag_id]
for(i in 1:nrow(presence_absence_long_df)){
  presence_absence_long_df$tag_id[i] = strsplit(presence_absence_long_df$tag_id[i], split = '_')[[1]][2]
}

## Merge with species from tagging data
presence_absence_long_df = merge(x = presence_absence_long_df, y = tagging_df[ ,c('tag_id', 'species')], on = 'tag_id')

## Drop date and tag pairs preceding the date the fish was tagged
indicies_to_drop = c()
for(i in nrow(presence_absence_long_df)){
  if(as.Date(tagging_df$datetime[tagging_df$tag_id == presence_absence_long_df$tag_id[i]]) <= presence_absence_long_df$date[i]){
    indicies_to_drop = c(indicies_to_drop, i)
  }
}
presence_absence_long_df = presence_absence_long_df[-indicies_to_drop, ]

## Get a list of active tags by date and species
active_tags_by_date = aggregate(tag_id ~ date + species, data = presence_absence_long_df, FUN = uniqueN)
  colnames(active_tags_by_date) = c('date', 'species', 'deployed_tags')

## Standardize tag counts by tags deployed and plot as % of tags detected per day by species
for(species in unique(presence_absence_long_df$species)){
  
  # Count number of tags detected daily by species 
  presence_absence_by_spp_df = aggregate(detected~date, data = presence_absence_long_df[presence_absence_long_df$species == species, ], FUN = sum)
  colnames(presence_absence_by_spp_df) = c('date', 'tags_detected')
  
  # Standardize daily tag count by the number of tags deployed
  presence_absence_by_spp_df = merge(x = presence_absence_by_spp_df, y = active_tags_by_date[active_tags_by_date$species == species, ], on = 'date')
  presence_absence_by_spp_df$percent_tags_detected = presence_absence_by_spp_df$detected / presence_absence_by_spp_df$deployed_tags
  
  # Make plot at species level
  ggplot(data = presence_absence_by_spp_df, mapping = aes(x = date, y = percent_tags_detected)) + 
    geom_bar(stat = 'identity') + 
    labs(title = species, x = 'Date', y = '% of tags detected') +
    ggsave(filename = paste('Detections Standardized By Species - ', species, '.pdf', sep = ''), path = figure_directory)
}

Bar plot vessel traffic by date

### LOGIC HERE TO GET TO # BOATS / DAY
## Get max_vessels at any given time, total_vessels


# Make plot for max_vessels 
max_vessels_plot = ggplot(data = vessels_per_day, mapping = aes(x = date, y = max_vessels)) + 
    geom_bar(stat = 'identity') + 
    labs(title = 'Maximum Number of Co-occuring Vessels Daily', x = 'Date', y = '# of Vessels') +
    ggsave(filename = paste('Maximum Number of Co-occuring Vessels Daily.pdf ', species, '.pdf', sep = ''), path = figure_directory)

# Make plot for tptal_vessels 
total_vessels_plot = ggplot(data = vessels_per_day, mapping = aes(x = date, y = total_vessels)) + 
    geom_bar(stat = 'identity') + 
    labs(title = 'Maximum Number of Co-occuring Vessels Daily', x = 'Date', y = '# of Vessels') +
    ggsave(filename = paste('Total Vessels Daily.pdf ', species, '.pdf', sep = ''), path = figure_directory)

print(max_vessels_plot)
print(total_vessels_plot)

Scatter plot x axis boat traffic, y axis presence / absence color by spp

Scatter plot x axis boat traffic, y axis detections per individual color by spp add error bars for daily detections

Residency and dispersal

Calculate 30 day moving average of residency, then plot against days since tagging

Statistical analysis

Calculate mean residency by spp (irregardless of time), then ANOVA by spp Use Tukey’s HSD to determine significance

## Tukey's Honestly Significant Differences between species
TukeyHSD(residence_by_species_anova)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = residence_metric ~ species, data = detection_stats)

$species
          diff          lwr       upr     p adj
b-a -0.1864600 -0.548699444 0.1757795 0.4333781
c-a  0.1765415 -0.229063083 0.5821461 0.5481175
c-b  0.3630015 -0.006985495 0.7329885 0.0555247

GLM comparing size and residency time by spp independent var (size, time at liberty) dependent (residency index)

summary(species_glm)

Call:
glm(formula = residence_metric ~ species + days_at_liberty * 
    species, family = binomial(logit), data = detection_stats)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.7145  -0.7787   0.4530   0.7932   2.2305  

Coefficients:
                          Estimate Std. Error z value Pr(>|z|)  
(Intercept)               1.644440   0.931881   1.765   0.0776 .
speciesb                 -0.662091   1.160109  -0.571   0.5682  
speciesc                  0.585109   1.614362   0.362   0.7170  
days_at_liberty          -0.007911   0.004178  -1.893   0.0583 .
speciesb:days_at_liberty -0.001790   0.005936  -0.302   0.7630  
speciesc:days_at_liberty  0.003451   0.006198   0.557   0.5776  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 59.071  on 51  degrees of freedom
Residual deviance: 41.195  on 46  degrees of freedom
AIC: 63.294

Number of Fisher Scoring iterations: 4

GLM comparing time in crater to vessel traffic

LS0tCnRpdGxlOiAiTW9sb2tpbmkgQW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgV3JpdHRlbiBieSBTdGV2ZSBTY2hlcnJlciAtIEp1bHkvQXVndXN0IDIwMjEKCiMjIEJhY2tncm91bmQKVGhpcyBub3RlYm9vayBkb2N1bWVudHMgcHJlbGltaW5hcnkgYW5hbHlzaXMgb2YgdHJhY2tpbmcgZGF0YSBmb3IgZmlzaCB0YWdnZWQgaW4gTW9sb2tpbmkgQ3JhdGVyIGJldHdlZW4gMjAyMC0wNS0xNiBhbmQgMjAyMS0wNS0yNC4gCgpUaGUgcHVycG9zZSBvZiB0aGlzIHN0dWR5IGlzIHRvIHVuZGVyc3RhbmQgaG93IGh1bWFuIGltcGFjdHMgYWZmZWN0IHRoZSBmaXNoIG9mIE1vbG9raW5pIENyYXRlcgoKV2UgYXJlIHBhcnRpY3VsYXJseSBpbnRlcmVzdGVkIGluIGFuc3dlcmluZyB0aGUgZm9sbG93aW5nIGh5cG90aGVzZXM6CjEuIElzIHRoZSBwcmVzZW5jZSBvZiBmaXNoIGFmZmVjdGVkIGJ5IHZlc3NlbCBwcmVzZW5jZQoKMi4gRG9lcyB0aGUgcHJvcG9ydGlvbiBvZiB0aW1lIGZpc2ggYXJlIHByZXNlbnQgd2l0aGluIHRoZSBjcmF0ZXIgbmVnYXRpdmVseSBjb3JyZWxhdGVkIHdpdGggdmVzc2VsIHByZXNlbmNlPwoKUHJvcG9zZWQgQXBwcm9hY2g6CjEuIEJlZ2luIGJ5IGNhbGN1bGF0aW5nIHRoZSBudW1iZXIgb2YgZWFjaCBzcGVjaWVzIHRhZ2dlZCBhbmQgYmFzaWMgc3VtbWFyeSBzdGF0aXN0aWNzCjIuIENhbGN1bGF0ZSBNZXRyaWNzCiAgLSBSZWNlaXZlciBVc2UKICAtIFBpYW5rYSdzIE5pY2hlIE92ZXJsYXAKICAtIHJlc2lkZW5jeQozLiBNYWtlIHRoZSBmb2xsb3dpbmcgcGxvdHMKICAtIE1hcCAtIFJlY2VpdmVyIGxvY2F0aW9ucwogIC0gTWFwIC0gQXZlcmFnZSByZWNlaXZlciB1c2UgYnkgU3BlY2llcwogIC0gU2NhdHRlcnBsb3QgLSBkYXkgbmlnaHQgcGxvdHMKICAtIEJhciBQbG90IC0gVGhlIG51bWJlciBvZiBkZXRlY3Rpb25zIHBlciBkYXkgKGluZGl2aWR1YWwpCiAgLSBCYXIgUGxvdCAtIFRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgZGV0ZWN0ZWQgKHNwZWNpZXMpCiAgLSBMaW5lIENoYXJ0IC0gVGhlIHByb3BvcnRpb24gb2YgaW5kaXZpZHVhbHMgZGV0ZWN0ZWQgbiBkYXlzIGFmdGVyIHRhZ2dpbmcgKDMwIGRheSBtb3ZpbmcgYXZlcmFnZSBieSBzcGVjaWVzKQogIC0gQmFyIFBsb3QgLSBEYWlseSB2ZXNzZWwgdHJhZmZpYwogIC0gU2NhdHRlciBQbG90IC0gdmVzc2VsIHRyYWZmaWMgdnMuIHByb3BvcnRpb24gb2YgZmlzaCBkZXRlY3RlZCBpbiBjcmF0ZXIgZGFpbHkgKHNjYXR0ZXJwbG90IGJ5IHNwZWNpZXMpCjQuIFBlcmZvcm0gdGhlIGZvbGxvd2luZyBzdGF0aXN0aWNhbCBUZXN0cwogIC0gQ29tcGFyZSBSZXNpZGVuY3kgUmF0ZXMgYnkgU3BlY2llcwogIC0gQ29tcGFyZSByZXNpZGVuY3kgYnkgc3BlY2llcywgc2l6ZSwgYW5kIHRpbWUgYXQgbGliZXJ0eQogIC0gQ3JlYXRlIGEgR0xNIGNvbXBhcmluZyAjIG9mIGluZGl2aWR1YWxzIGluIGNyYXRlciByZWdyZXNzZWQgYWdhaW5zdCBib2F0IHRyYWZmaWMgYW5kIHNwZWNpZXMgdXNpbmcgQVIoMSkgdGVybSBvbiBkZXBlbmRlbnQgdmFyaWFibGUgb24gc29tZSB0aW1lIHNjYWxlIChkYWlseT8gNiBob3Vycz8gZGVwZW5kcyBvbiByZXNvbHV0aW9uIG9mIHZlc3NlbCBkYXRhKQoKIyBXb3Jrc3BhY2UgU2V0dXAKIyMgRXN0YWJsaXNoIERpcmVjdG9yeSBIZWlyYXJjaHkKYGBge3J9CnByb2plY3RfZGlyZWN0b3J5ID0gJy9Vc2Vycy9zdGVwaGVuc2NoZXJyZXIvRG9jdW1lbnRzL1Byb2dyYW1taW5nL1Byb2plY3RzL01vbG9raW5pJwpzY3JpcHRzX2RpcmVjdG9yeSA9IGZpbGUucGF0aChwcm9qZWN0X2RpcmVjdG9yeSwgJ0FuYWx5c2lzIFNjcmlwdHMnKQpkYXRhX2RpcmVjdG9yeSA9IGZpbGUucGF0aChwcm9qZWN0X2RpcmVjdG9yeSwgJ0RhdGEnKQpyZXN1bHRzX2RpcmVjdG9yeSA9IGZpbGUucGF0aChwcm9qZWN0X2RpcmVjdG9yeSwgJ1Jlc3VsdHMnKQpmaWd1cmVfZGlyZWN0b3J5ID0gZmlsZS5wYXRoKHJlc3VsdHNfZGlyZWN0b3J5LCAnRmlndXJlcycpCgpgYGAKCiMjIFNvdXJjZSBwYWNrYWdlIGRlcGVuZGVuY2llcyBhbmQgdXRpbGl0eSBmdW5jdGlvbnMgZnJvbSAnVXRpbGl0eSBGdW5jdGlvbnMuUicgZmlsZQpgYGB7cn0Kc291cmNlKGZpbGUucGF0aChzY3JpcHRzX2RpcmVjdG9yeSwgJ1V0aWxpdHkgRnVuY3Rpb25zLlInKSkKYGBgCgojIyBMb2FkIERhdGEKLSBsb2FkIHZhcmlvdXMgZGF0YWZpbGVzIApgYGB7cn0KIyMgRmlsZXMgZnJvbSBWVUUgCm1vbG9fZGYgPSBsb2FkX3ZlbWNvX2RhdGEoZmlsZS5wYXRoKGRhdGFfZGlyZWN0b3J5LCAnVlVFX0V4cG9ydC5jc3YnKSkKZmFsc2VfZGV0ZWN0aW9uc19kZiA9IGxvYWRfZmRmX3JlcG9ydChmaWxlLnBhdGgoZGF0YV9kaXJlY3RvcnksICdGREEuY3N2JykpCgojIyBWZXNzZWwgVHJhZmZpYyBkYXRhCnZlc3NlbF9kZiA9IAoKIyMgTWV0YWRhdGEgRmlsZXMKdGFnZ2luZ19kZiA9IGxvYWRfdGFnZ2luZ19kYXRhKGZpbGUucGF0aChkYXRhX2RpcmVjdG9yeSwgKSkKIyMgdGVtcCAKdGFnZ2luZ19kZiA9IGRhdGEuZnJhbWUodGFnX2lkID0gZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciR0YWdfaWQsIHNwZWNpZXMgPSBzYW1wbGUoYygnYScsICdiJywgJ2MnKSwgc2l6ZSA9IG5yb3coZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciksIHJlcGxhY2UgPSBUKSkKCnJlY2VpdmVyX2RmID0gbG9hZF9yZWNlaXZlcl9kYXRhKGZpbGUucGF0aChkYXRhX2RpcmVjdG9yeSwgKSkKYGBgCgojIyBDbGVhbiBEYXRhCi0gQXNzb2NpYXRlIGRldGVjdGlvbnMgd2l0aCB0aW1lIG9mIGRheSAoZGF5LCBuaWdodCwgZGF3biwgZHVzaykKLSBSZW1vdmUgZGV0ZWN0aW9ucyBmcm9tIHRhZ3Mgbm90IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHN0dWR5Ci0gUmVtb3ZlIGZhbHNlIGRldGVjdGlvbnMKYGBge3J9CiMjIEFzc29jaWF0ZSBkZXRlY3Rpb25zIHdpdGggdGltZSBvZiBkYXkKbW9sb19kZiA9IGdldF90aW1lX29mX2RheShtb2xvX2RmKQoKIyMgUmVtb3ZlIGlycmVsZXZhbnQgdGFncwojIG1vbG9fZGYgPSBtb2xvX2RmW21vbG9fZGYkZnVsbF90YWdfaWQgJWluJSB0YWdnaW5nX2RmJHZlbV90YWdfaWQsIF0KCiMjIEZpbHRlciBmYWxzZSBkZXRlY3Rpb25zCm1vbG9fZGYgPSBmaWx0ZXJfZmFsc2VfZGV0ZWN0aW9ucyhtb2xvX2RmKQpgYGAKCiMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcwojIyBDb3VudCBvZiBpbmRpdmlkdWFscyB0YWdnZWQgYnkgc3BlY2llcwpgYGB7cn0KdGFnc19ieV9zcGVjaWVzID0gYWdncmVnYXRlKHRhZ19pZCB+IHNwZWNpZXMsIGRhdGEgPSB0YWdnaW5nX2RmLCBGVU4gPSB1bmlxdWVOKQogIGNvbG5hbWVzKHRhZ3NfYnlfc3BlY2llcykgPSBjKCdzcGVjaWVzJywgJ25fdGFnZ2VkJykKcHJpbnQodGFnc19ieV9zcGVjaWVzKQpgYGAKCiMjIFN1bW1hcnkgU3RhdGlzdGljcwpgYGB7cn0KIyBUaW1lIGF0IGxpYmVydHkKdGltZV9hdF9saWJlcnR5ID0gY2FsY3VsYXRlX3RpbWVfYXRfbGliZXJ0eShtb2xvX2RmKQoKIyBEYXlzIERldGVjdGVkCmRheXNfZGV0ZWN0ZWQgPSBjYWxjdWxhdGVfZGF5c19kZXRlY3RlZChtb2xvX2RmKQoKIyAlIG9mIGRheXMgZGV0ZWN0ZWQKZGV0ZWN0aW9uX3N0YXRzID0gbWVyZ2UoeCA9IGRheXNfZGV0ZWN0ZWQsIHkgPSB0aW1lX2F0X2xpYmVydHlbICxjKCd0YWdfaWQnLCAnZGF5c19hdF9saWJlcnR5JyldLCBvbi54ID0gJ3RhZ19pZCcsIG9uLnkgPSAndGFnX2lkJykKZGV0ZWN0aW9uX3N0YXRzJHBlcmNlbnRfZGF5c19kZXRlY3RlZCA9IHJvdW5kKGRldGVjdGlvbl9zdGF0cyR1bmlxdWVfZGF5cyAvIGRldGVjdGlvbl9zdGF0cyRkYXlzX2F0X2xpYmVydHksIDQpICogMTAwCgojIE1lcmdlIHdpdGggdGFnZ2luZyBkYXRhIHRvIGdldCBmaXNoIGluZm8KZGV0ZWN0aW9uX3N0YXRzID0gbWVyZ2UoeCA9IHRhZ2dpbmdfZGZbICxjKCd0YWdnaW5nX2RhdGV0aW1lJywgJ3NwZWNpZXMnLCAndGFnX2lkJywgJ2ZvcmtfbGVuZ3RoX2NtJywgKV0sIHkgPSBkZXRlY3Rpb25fc3RhdHMsIG9uLnggPSAndGFnX2lkJywgb24ueSA9ICd0YWdfaWQnKQpkZXRlY3Rpb25fc3RhdHMgPSBkZXRlY3Rpb25fc3RhdHNbICxvcmRlcihkZXRlY3Rpb25fc3RhdHMkc3BlY2llcywgZGV0ZWN0aW9uX3N0YXRzJHRhZ2dpbmdfZGF0ZXRpbWUsIGRldGVjdGlvbl9zdGF0cyR0YWdfaWQpXQpwcmludChkZXRlY3Rpb25fc3RhdHMpCmBgYAoKIyBNZXRyaWMgQ2FsY3VsYXRpb25zCiMjIGluZGV4IG9mIHJlY2VpdmVyIHVzZQpgYGB7cn0KIyMgc3VtIGFsbCBzcHAsIHN1bSBhbGwgaW5kaXZpZHVhbHMgKGRldGVjdGlvbnMgb2YgdGFnIGF0IGdpdmVuIHJlY2lldmVyIC8gYWxsIGRldGVjdGlvbnMgb2YgdGFnKQoKIyMgQ2FsY3VsYXRlIHVuaXF1ZSBkZXRlY3Rpb25zIHBlciB0YWcgcGVyIHJlY2VpdmVyIHN0YXRpb24KZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciA9IGFnZ3JlZ2F0ZShkYXRldGltZX50YWdfaWQrcmVjZWl2ZXIsIGRhdGEgPSBtb2xvX2RmLCBGVU4gPSB1bmlxdWVOKSAjIGFnZ3JlZ2F0ZShkYXRldGltZX50YWdfaWQrcmVjZWl2ZXIrc3BlY2llcywgZGF0YSA9IG1vbG9fZGYsIEZVTiA9IHVuaXF1ZU4pCmNvbG5hbWVzKGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIpID0gYygndGFnX2lkJywgJ3JlY2VpdmVyJywgJ2RldGVjdGlvbnMnKSAjIGNvbG5hbWVzKGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIpID0gYygndGFnX2lkJywgJ3JlY2VpdmVyJywgJ3NwZWNpZXMnLCAnZGV0ZWN0aW9ucycpCgojIyBDYWxjdWxhdGUgcmVjZWl2ZXIgdXNlIG1ldHJpYyBmb3IgZWFjaCBmaXNoIGFuZCByZWNlaXZlciBwYWlyCmRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIkcmVjZWl2ZXJfdXNlID0gMApmb3IgKHNwZWNpZXMgaW4gZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciRzcGVjaWVzKXsKICBmb3IgKGkgaW4gMTpucm93KGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIpKXsKICAgIGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIkcmVjZWl2ZXJfdXNlW2ldID0gZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciRkZXRlY3Rpb25zW2ldIC8gc3VtKGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIkZGV0ZWN0aW9uc1tkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyJHRhZ19pZCA9PSBkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyJHRhZ19pZFtpXV0pCiAgfQp9CgojIyBDYWxjdWxhdGUgYXZlcmFnZSByZWNlaXZlciB1c2UgbWV0cmljIGZvciBlYWNoIHRhZyAtIE9taXQgc3RhdGlvbnMgd2l0aCBubyB1c2UgYXMgdGhpcyB3b3VsZCBiaWFzIG1ldHJpYwppbmR2aWR1YWxfcmVjZWl2ZXJfdXNlID0gYWdncmVnYXRlKHJlY2VpdmVyX3VzZX50YWdfaWQrc3BlY2llcywgZGF0YSA9IGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXJbZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciRyZWNlaXZlcl91c2UgPiAwLCBdLCBGVU4gPSBtZWFuKQoKIyMgQWRkIHRoaXMgaW5mb3JtYXRpb24gdG8gZGV0ZWN0aW9uX3N0YXRzCmRldGVjdGlvbl9zdGF0cyA9IG1lcmdlKGRldGVjdGlvbl9zdGF0cywgaW5kdmlkdWFsX3JlY2VpdmVyX3VzZSwgb24gPSAndGFnX2lkJykKCiMjIENhbGN1bGF0ZSByZWNlaXZlciB1c2UgbWV0cmljIGJ5IHNwZWNpZXMKc3BlY2llc19yZWNlaXZlcl91c2UgPSBhZ2dyZWdhdGUoaW5kZXhfb2ZfcmVjZWl2ZXJfdXNlfnNwZWNpZXMsIGRhdGEgPSBpbmR2aWR1YWxfcmVjZWl2ZXJfdXNlLCBGVU4gPSBtZWFuKQpjb2xuYW1lcyhzcGVjaWVzX3JlY2VpdmVyX3VzZSkgPSBjKCdzcGVjaWVzJywgJ3JlY2VpdmVyX3VzZScpCgpwcmludChzcGVjaWVzX3JlY2VpdmVyX3VzZSkKYGBgIAojIyBDYWxjdWxhdGUgUGlhbmthJ3MgTmljaGUgT3ZlcmxhcCBJbmRleCAtIFBpYW5rYSAoMTk3MykgVGhlIFN0cnVjdHVyZSBvZiBMaXphcmQgQ29tbXVuaXRpZXMKIDAgPSBubyBvdmVybGFwLCAxID0gcGVyZmVjdCBvdmVybGFwCmBgYHtyfQojIyBHZXQgc3BlY2llcyBhc3NvY2lhdGVkIHdpdGggZWFjaCB0YWcgaW4gZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlcgpkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyID0gbWVyZ2UoeCA9IGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIsIHkgPSB0YWdnaW5nX2RmWyAsYygndGFnX2lkJywgJ3NwZWNpZXMnKV0sIG9uID0gJ3RhZ19pZCcpCgojIyBBZ2dyZWdhdGUgZGF0YSBhdmVyYWdlZCBieSBzcGVjaWVzCnJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXMgPSBhZ2dyZWdhdGUoaW5kZXhfb2ZfcmVjZWl2ZXJfdXNlIH4gc3BlY2llcyArIHJlY2VpdmVyICwgZGF0YSA9IGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIsIEZVTiA9IG1lYW4pCiAgY29sbmFtZXMocmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llcykgPSBjKCdzcGVjaWVzJywgJ3JlY2VpdmVyJywgJ2F2Z191c2VfaW5kZXgnKQogIAojIyBSZXNoYXBlIGZyb20gTG9uZyB0byBXaWRlIGZvcm1hdApyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGUgPSBkY2FzdChyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzLCBzcGVjaWVzIH4gcmVjZWl2ZXIpCgojIyBHZXQgYWxsIHNwZWNpZXMgY29tYmluYXRpb25zIApzcGVjaWVzX2NvbWJvcyA9IGRhdGEuZnJhbWUoJ3NwZWNpZXNfMScgPSAnYScsICdzcGVjaWVzXzInID0gJ2EnKQpmb3IgKGkgaW4gMTpucm93KHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSkpewogICAgaWYoaSAhPSBucm93KHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSkpewogICAgZm9yIChqIGluIChpKzEpOm5yb3cocmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlKSl7CiAgICAgIHNwZWNpZXNfY29tYm9zID0gcmJpbmQoc3BlY2llc19jb21ib3MsIGRhdGEuZnJhbWUoJ3NwZWNpZXNfMScgPSByZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGUkc3BlY2llc1tpXSwgJ3NwZWNpZXNfMicgPSByZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGUkc3BlY2llc1tqXSkpCiAgICAgIHByaW50KGopCiAgICB9CiAgfQp9CgojIyBDYWxjdWxhdGUgUGlhbmthJ3MgaW5kZXggZm9yIGFsbCBwYWlycwpzcGVjaWVzX2NvbWJvcyRwaWFua2FfaW5kZXggPSAwCmZvcihpIGluIDE6bnJvdyhzcGVjaWVzX2NvbWJvcykpewogIHNwZWNpZXNfY29tYm9zJHBpYW5rYV9pbmRleFtpXSA9IHN1bShyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGVbcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlJHNwZWNpZXMgPT0gc3BlY2llc19jb21ib3Mkc3BlY2llc18xW2ldLCAtMV0gKiAKICAgICByZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGVbcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlJHNwZWNpZXMgPT0gc3BlY2llc19jb21ib3Mkc3BlY2llc18yW2ldLCAtMV0pIC8KICAgIChzcXJ0KHN1bShyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGVbcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlJHNwZWNpZXMgPT0gc3BlY2llc19jb21ib3Mkc3BlY2llc18xW2ldLCAtMV0gXiAyKSAqIAogICAgc3VtKHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZVtyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGUkc3BlY2llcyA9PSBzcGVjaWVzX2NvbWJvcyRzcGVjaWVzXzJbaV0sIC0xXSBeIDIpKSkKfQoKcHJpbnQoc3BlY2llc19jb21ib3MpCmBgYAoKIyMgUGxvdHMKU3R1ZHkgQXJlYQpgYGB7cn0KIyMgUGxvdCBzdHVkeSBhcmVhIGFuZCByZWNlaXZlcnMKbGlicmFyeShnZ21hcCkKCm1vbG9fYmFzZW1hcCA9IGdldF9tYXAobG9jYXRpb24gPSBjKGxvbiA9IC0xNTYuNDk2MzMxLCBsYXQgPSAyMC42MzMwMDcpLCB6b29tID0gMTYsIG1hcHR5cGUgPSAnc2F0ZWxsaXRlJykKcmVjZWl2ZXJfbWFwID0gZ2dtYXAobW9sb19iYXNlbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IG1vbG9fZGZbbW9sb19kZiRyZWNlaXZlciAhPSAnVGFnZ2luZyBMb2NhdGlvbicsIF0sIG1hcHBpbmcgPSBhZXMoeCA9IGxvbiwgeSA9IGxhdCksIGNvbCA9ICdyZWQnKSArIGxhYnMoeCA9ICfCsExvbmdpdHVkZScsIHkgPSAnwrBMYXRpdHVkZScpICsgZ2dzYXZlKGZpbGVuYW1lID0gJ1JlY2VpdmVyIExvY2F0aW9ucyBHb29nbGUgTWFwLnBkZicsIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQpwcmludChyZWNlaXZlcl9tYXApCmBgYAoKIyMjIFNwZWNpZXMgVXNlIFBsb3RzCmBgYHtyfQojIyBDYWxjdWxhdGUgbWVyZ2UgZGV0ZWN0aW9ucyBvZiB0YWcgcGVyIHJlY2VpdmVyIHdpdGggc3BlY2llcyBpbmZvcm1hdGlvbgpkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyID0gbWVyZ2UoeCA9IGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIsIHkgPSB0YWdnaW5nX2RmWyAsYygndGFnX2lkJywgJ3NwZWNpZXMnKV0sIG9uID0gJ3RhZ19pZCcpCgojIyBHZXQgYXZlcmFnZSB1c2Ugb2YgcmVjZWl2ZXIgYnkgc3BlY2llcyAKc3BlY2llc19yZWNlaXZlcl91c2UgPSBhZ2dyZWdhdGUoaW5kZXhfb2ZfcmVjZWl2ZXJfdXNlfnNwZWNpZXMrcmVjZWl2ZXIsIGRhdGEgPSBkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyLCBGVU4gPSBtZWFuKQogIGNvbG5hbWVzKHNwZWNpZXNfcmVjZWl2ZXJfdXNlKSA9IGMoJ3NwZWNpZXMnLCAncmVjZWl2ZXInICwgJ3JlY2VpdmVyX3VzZScpCiAgCiMjIE1lcmdlIHdpdGggbGF0IGxvbiBwb3NpdGlvbnMgZm9yIGVhY2ggcmVjZWl2ZXIgZnJvbSBtb2xvX2RmCnJlY2VpdmVyX3Bvc3Rpb25zID0gIHVuaXF1ZShtb2xvX2RmWyAsYygncmVjZWl2ZXInLCAnbGF0JywgJ2xvbicpXSkKc3BlY2llc19yZWNlaXZlcl91c2UgPSBtZXJnZSh4ID0gc3BlY2llc19yZWNlaXZlcl91c2UsIHkgPSByZWNlaXZlcl9wb3N0aW9ucywgb24gPSAncmVjZWl2ZXInLCBhbGwueCA9IFQsIGFsbC55ID0gRikKCiMjIE1ha2Ugc3BlY2llcyBwbG90cyBmb3IgcmVjZWl2ZXIgdXNlCmZvcihzcGVjaWVzIGluIHNwZWNpZXNfcmVjZWl2ZXJfdXNlJHNwZWNpZXMpewogIHJlY2VpdmVyX3VzZV9ieV9zcHAgPSBnZ21hcChtb2xvX2Jhc2VtYXApICsgCiAgICBnZW9tX3BvaW50KGRhdGEgPSBzcGVjaWVzX3JlY2VpdmVyX3VzZVtzcGVjaWVzX3JlY2VpdmVyX3VzZSRzcGVjaWVzID09IHNwZWNpZXMsIF0sIAogICAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBsb24sIHkgPSBsYXQsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAgcmVjZWl2ZXJfdXNlKSkgKyAKICAgIGxhYnMoeCA9ICfCsExvbmdpdHVkZScsIHkgPSAnwrBMYXRpdHVkZScpICsKICAgIGdnc2F2ZShmaWxlbmFtZSA9IHBhc3RlKCdSZWNlaXZlciBVc2UgYnkgJywgc3BlY2llcywgJy5wZGYnLCBzZXAgPSAnJyksIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQogIHByaW50KHJlY2VpdmVyX3VzZV9ieV9zcHApCn0KYGBgCgojIyMgRGF5IE5pZ2h0IFBsb3RzCmBgYHtyfQojIyMgRGF5IE5pZ2h0IFBsb3RzCiMjIEZvciBhbGwgZmlzaApwbG90X2RheV9uaWdodChtb2xvX2RmLCBwbG90X3RpdGxlID0gJ0FsbCBGaXNoJykKCiMjIEJ5IFNwZWNpZXMKZm9yIChzcHAgaW4gdW5pcXVlKHRhZ2dpbmdfZGYkc3BlY2llcykpewogIHBsb3RfZGF5X25pZ2h0KG1vbG9fZGZbbW9sb19kZiR0YWdfaWQgPT0gdGFnZ2luZ19kZiR0YWdfaWRbdGFnZ2luZ19kZiRzcGVjaWVzID09IHNwcF0sIF0sIHBsb3RfdGl0bGUgPSBzcHApCn0KCiMjIEJ5IEluZGl2aWR1YWwKZm9yICh0YWdfaWQgaW4gbW9sb19kZiR0YWdfaWQpewogIHBsb3RfZGF5X25pZ2h0KG1vbG9fZGZbbW9sb19kZiR0YWdfaWQgPT0gdGFnX2lkLCBdLCBwbG90X3RpdGxlID0gcGFzdGUodGFnZ2luZ19kZiRzcGVjaWVzW3RhZ2dpbmdfZGYkdGFnX2lkID09IHRhZ19pZF0sICctIFRhZycsIGFzLmNoYXJhY3Rlcih0YWdfaWQpLCBzZXAgPSAnICcpKQp9CmBgYAoKCiMjIyBCYXJwbG90IG9mIGRldGVjdGlvbnMgYnkgZGF0ZQpgYGB7cn0KIyMjIEJhciBwbG90IG9mIGRldGVjdGlvbnMgaW4gY3JhdGVyIGJ5IGRhdGUgCmRldGVjdGlvbnNfcGVyX2RheV9kZiA9IGNvdW50X2RldGVjdGlvbnNfcGVyX2RhdGUobW9sb19kZikKCiMjIEJhcnBsb3Qgb2YgZGV0ZWN0aW9ucyBieSBpbmRpdmlkdWFsCmZvcihjb2x1bW4gaW4gY29sbmFtZXMoZGV0ZWN0aW9uc19wZXJfZGF5X2RmKVsyOm5jb2woZGV0ZWN0aW9uc19wZXJfZGF5X2RmKV0pewogIGdncGxvdChkYXRhID0gZGV0ZWN0aW9uc19wZXJfZGF5X2RmLCBtYXBwaW5nID0gYWVzX3N0cmluZyh4ID0gJ2RhdGUnLCB5ID0gY29sdW1uKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsgCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoJ1RhZyAnLCBzdHJzcGxpdCh4ID0gY29sdW1uLCBzcGxpdCA9ICdfJylbWzFdXVsyXSwgc2VwID0gJycpLCB4ID0gJ0RhdGUnLCB5ID0gJ0RldGVjdGlvbnMnKSArIAogICAgZ2dzYXZlKGZpbGVuYW1lID0gcGFzdGUoJ0RhaWx5IERldGVjdGlvbiBCYXJwbG90IC0nLCBjb2x1bW4sICcucGRmJyksIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQp9CgoKIyMgRGV0ZWN0aW9ucyBieSBzcGVjaWVzCgojIyBCYXJwbG90IG9mIGFsbCBkZXRlY3Rpb25zCmFnZ3JlZ2F0ZShkYXRhID0KYGBgCgojIyMgQmFyIHBsb3QgIyBvZiBGaXNoIChzdGFuZGFyZGl6ZWQgcGVyY2VudCBvZiBmaXNoIHRhZ2dlZCB0byBkYXRlKSBieSBkYXRlIGFuZCBTcHAKYGBge3J9CiMjIENvbnZlcnQgZGV0ZWN0aW9uc19wZXJfZGF5IHRvIHByZXNlbmNlL2Fic2VuY2UKcHJlc2VuY2VfYWJzZW5jZV93aWRlX2RmID0gZGV0ZWN0aW9uc19wZXJfZGF5X2RmCmZvciAoaSBpbiAyOm5jb2wocHJlc2VuY2VfYWJzZW5jZV93aWRlX2RmKSl7CiAgcHJlc2VuY2VfYWJzZW5jZV93aWRlX2RmWyAsaV0gPSBhcy5udW1lcmljKHByZXNlbmNlX2Fic2VuY2Vfd2lkZV9kZlsgLGldID4gMCkKfQoKIyMgQ29udmVydCBmcm9tIHdpZGUgdG8gbG9uZyBmb3JtYXQKcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmID0gbWVsdChwcmVzZW5jZV9hYnNlbmNlX3dpZGVfZGYsIGlkLnZhcnMgPSBjKCdkYXRlJyksIG1lYXN1cmUudmFycyA9IGNvbG5hbWVzKHByZXNlbmNlX2Fic2VuY2Vfd2lkZV9kZilbMjpuY29sKHByZXNlbmNlX2Fic2VuY2Vfd2lkZV9kZildLCB2YXJpYWJsZS5uYW1lID0gJ3RhZ19pZCcsIHZhbHVlLm5hbWUgPSAnZGV0ZWN0ZWQnKQoKIyBEcm9wICd0YWdfJyBwcmVmaXggZnJvbSB0YWdfaWQgY29sdW1uIGZvciBtYXRjaGluZyBwdXJwb3NlcwpwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkdGFnX2lkID0gbGV2ZWxzKHByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiR0YWdfaWQpW3ByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiR0YWdfaWRdCmZvcihpIGluIDE6bnJvdyhwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYpKXsKICBwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkdGFnX2lkW2ldID0gc3Ryc3BsaXQocHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmJHRhZ19pZFtpXSwgc3BsaXQgPSAnXycpW1sxXV1bMl0KfQoKIyMgTWVyZ2Ugd2l0aCBzcGVjaWVzIGZyb20gdGFnZ2luZyBkYXRhCnByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiA9IG1lcmdlKHggPSBwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYsIHkgPSB0YWdnaW5nX2RmWyAsYygndGFnX2lkJywgJ3NwZWNpZXMnKV0sIG9uID0gJ3RhZ19pZCcpCgojIyBEcm9wIGRhdGUgYW5kIHRhZyBwYWlycyBwcmVjZWRpbmcgdGhlIGRhdGUgdGhlIGZpc2ggd2FzIHRhZ2dlZAppbmRpY2llc190b19kcm9wID0gYygpCmZvcihpIGluIG5yb3cocHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmKSl7CiAgaWYoYXMuRGF0ZSh0YWdnaW5nX2RmJGRhdGV0aW1lW3RhZ2dpbmdfZGYkdGFnX2lkID09IHByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiR0YWdfaWRbaV1dKSA8PSBwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkZGF0ZVtpXSl7CiAgICBpbmRpY2llc190b19kcm9wID0gYyhpbmRpY2llc190b19kcm9wLCBpKQogIH0KfQpwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYgPSBwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGZbLWluZGljaWVzX3RvX2Ryb3AsIF0KCiMjIEdldCBhIGxpc3Qgb2YgYWN0aXZlIHRhZ3MgYnkgZGF0ZSBhbmQgc3BlY2llcwphY3RpdmVfdGFnc19ieV9kYXRlID0gYWdncmVnYXRlKHRhZ19pZCB+IGRhdGUgKyBzcGVjaWVzLCBkYXRhID0gcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmLCBGVU4gPSB1bmlxdWVOKQogIGNvbG5hbWVzKGFjdGl2ZV90YWdzX2J5X2RhdGUpID0gYygnZGF0ZScsICdzcGVjaWVzJywgJ2RlcGxveWVkX3RhZ3MnKQoKIyMgU3RhbmRhcmRpemUgdGFnIGNvdW50cyBieSB0YWdzIGRlcGxveWVkIGFuZCBwbG90IGFzICUgb2YgdGFncyBkZXRlY3RlZCBwZXIgZGF5IGJ5IHNwZWNpZXMKZm9yKHNwZWNpZXMgaW4gdW5pcXVlKHByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiRzcGVjaWVzKSl7CiAgCiAgIyBDb3VudCBudW1iZXIgb2YgdGFncyBkZXRlY3RlZCBkYWlseSBieSBzcGVjaWVzIAogIHByZXNlbmNlX2Fic2VuY2VfYnlfc3BwX2RmID0gYWdncmVnYXRlKGRldGVjdGVkfmRhdGUsIGRhdGEgPSBwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGZbcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmJHNwZWNpZXMgPT0gc3BlY2llcywgXSwgRlVOID0gc3VtKQogIGNvbG5hbWVzKHByZXNlbmNlX2Fic2VuY2VfYnlfc3BwX2RmKSA9IGMoJ2RhdGUnLCAndGFnc19kZXRlY3RlZCcpCiAgCiAgIyBTdGFuZGFyZGl6ZSBkYWlseSB0YWcgY291bnQgYnkgdGhlIG51bWJlciBvZiB0YWdzIGRlcGxveWVkCiAgcHJlc2VuY2VfYWJzZW5jZV9ieV9zcHBfZGYgPSBtZXJnZSh4ID0gcHJlc2VuY2VfYWJzZW5jZV9ieV9zcHBfZGYsIHkgPSBhY3RpdmVfdGFnc19ieV9kYXRlW2FjdGl2ZV90YWdzX2J5X2RhdGUkc3BlY2llcyA9PSBzcGVjaWVzLCBdLCBvbiA9ICdkYXRlJykKICBwcmVzZW5jZV9hYnNlbmNlX2J5X3NwcF9kZiRwZXJjZW50X3RhZ3NfZGV0ZWN0ZWQgPSBwcmVzZW5jZV9hYnNlbmNlX2J5X3NwcF9kZiRkZXRlY3RlZCAvIHByZXNlbmNlX2Fic2VuY2VfYnlfc3BwX2RmJGRlcGxveWVkX3RhZ3MKICAKICAjIE1ha2UgcGxvdCBhdCBzcGVjaWVzIGxldmVsCiAgZ2dwbG90KGRhdGEgPSBwcmVzZW5jZV9hYnNlbmNlX2J5X3NwcF9kZiwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSwgeSA9IHBlcmNlbnRfdGFnc19kZXRlY3RlZCkpICsgCiAgICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICAgIGxhYnModGl0bGUgPSBzcGVjaWVzLCB4ID0gJ0RhdGUnLCB5ID0gJyUgb2YgdGFncyBkZXRlY3RlZCcpICsKICAgIGdnc2F2ZShmaWxlbmFtZSA9IHBhc3RlKCdEZXRlY3Rpb25zIFN0YW5kYXJkaXplZCBCeSBTcGVjaWVzIC0gJywgc3BlY2llcywgJy5wZGYnLCBzZXAgPSAnJyksIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQp9CgpgYGAKCiMjIyBCYXIgcGxvdCB2ZXNzZWwgdHJhZmZpYyBieSBkYXRlCmBgYHtyfQojIyMgTE9HSUMgSEVSRSBUTyBHRVQgVE8gIyBCT0FUUyAvIERBWQojIyBHZXQgbWF4X3Zlc3NlbHMgYXQgYW55IGdpdmVuIHRpbWUsIHRvdGFsX3Zlc3NlbHMKCgojIE1ha2UgcGxvdCBmb3IgbWF4X3Zlc3NlbHMgCm1heF92ZXNzZWxzX3Bsb3QgPSBnZ3Bsb3QoZGF0YSA9IHZlc3NlbHNfcGVyX2RheSwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSwgeSA9IG1heF92ZXNzZWxzKSkgKyAKICAgIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogICAgbGFicyh0aXRsZSA9ICdNYXhpbXVtIE51bWJlciBvZiBDby1vY2N1cmluZyBWZXNzZWxzIERhaWx5JywgeCA9ICdEYXRlJywgeSA9ICcjIG9mIFZlc3NlbHMnKSArCiAgICBnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZSgnTWF4aW11bSBOdW1iZXIgb2YgQ28tb2NjdXJpbmcgVmVzc2VscyBEYWlseS5wZGYgJywgc3BlY2llcywgJy5wZGYnLCBzZXAgPSAnJyksIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQoKIyBNYWtlIHBsb3QgZm9yIHRwdGFsX3Zlc3NlbHMgCnRvdGFsX3Zlc3NlbHNfcGxvdCA9IGdncGxvdChkYXRhID0gdmVzc2Vsc19wZXJfZGF5LCBtYXBwaW5nID0gYWVzKHggPSBkYXRlLCB5ID0gdG90YWxfdmVzc2VscykpICsgCiAgICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICAgIGxhYnModGl0bGUgPSAnTWF4aW11bSBOdW1iZXIgb2YgQ28tb2NjdXJpbmcgVmVzc2VscyBEYWlseScsIHggPSAnRGF0ZScsIHkgPSAnIyBvZiBWZXNzZWxzJykgKwogICAgZ2dzYXZlKGZpbGVuYW1lID0gcGFzdGUoJ1RvdGFsIFZlc3NlbHMgRGFpbHkucGRmICcsIHNwZWNpZXMsICcucGRmJywgc2VwID0gJycpLCBwYXRoID0gZmlndXJlX2RpcmVjdG9yeSkKCnByaW50KG1heF92ZXNzZWxzX3Bsb3QpCnByaW50KHRvdGFsX3Zlc3NlbHNfcGxvdCkKYGBgCgoKIyMjIFNjYXR0ZXIgcGxvdCB4IGF4aXMgYm9hdCB0cmFmZmljLCB5IGF4aXMgcHJlc2VuY2UgLyBhYnNlbmNlIGNvbG9yIGJ5IHNwcApgYGB7cn0KCmBgYAoKIyMjIFNjYXR0ZXIgcGxvdCB4IGF4aXMgYm9hdCB0cmFmZmljLCB5IGF4aXMgZGV0ZWN0aW9ucyBwZXIgaW5kaXZpZHVhbCBjb2xvciBieSBzcHAgYWRkIGVycm9yIGJhcnMgZm9yIGRhaWx5IGRldGVjdGlvbnMKYGBge3J9CgpgYGAKCiMgUmVzaWRlbmN5IGFuZCBkaXNwZXJzYWwKYGBge3J9CiMjIENhbGN1bGF0ZSByZXNpZGVuY3kKZGV0ZWN0aW9uX3N0YXRzJHJlc2lkZW5jZV9tZXRyaWMgPSBkZXRlY3Rpb25fc3RhdHMkdW5pcXVlX2RheXMgLyBkZXRlY3Rpb25fc3RhdHMkZGF5c19hdF9saWJlcnR5CgojIyBBc3NpZ24gcmVzaWRlbmNlIGNhdGVnb3J5OiBsb3cgPSA8IDMzJSwgbWVkaXVtID0gMzMgLSA2NiwgaGlnaCA9ID49IDY2IChUaW5oYW4gZXQgYWwuIDIwMTQpIC0KZGV0ZWN0aW9uX3N0YXRzJHJlc2lkZW5jZV9jYXRlZ29yeSA9ICdMb3cnCmZvciAoaSBpbiAxOm5yb3coZGV0ZWN0aW9uX3N0YXRzKSl7CiAgaWYgKGRldGVjdGlvbl9zdGF0cyRyZXNpZGVuY2VfbWV0cmljW2ldID49ICgxLzMpKSB7CiAgICBkZXRlY3Rpb25fc3RhdHMkcmVzaWRlbmNlX2NhdGVnb3J5W2ldID0gJ01lZGl1bScKICB9CiAgaWYgKGRldGVjdGlvbl9zdGF0cyRyZXNpZGVuY2VfbWV0cmljW2ldID49ICgyLzMpKSB7CiAgICBkZXRlY3Rpb25fc3RhdHMkcmVzaWRlbmNlX2NhdGVnb3J5W2ldID0gJ0hpZ2gnCiAgfQp9CgojIyBDcmVhdGUgZ3JvdXBlZCBiYXJwbG90IG9mIHJlc2lkZW5jeSBieSBzcGVjaWVzCmdncGxvdChkYXRhID0gZXhwZXJpbWVudCwgbWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9Y2FyX2NvdW50LCBmaWxsPXNpdGUpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSkKCmBgYAoKIyMgQ2FsY3VsYXRlIDMwIGRheSBtb3ZpbmcgYXZlcmFnZSBvZiByZXNpZGVuY3ksIHRoZW4gcGxvdCBhZ2FpbnN0IGRheXMgc2luY2UgdGFnZ2luZwpgYGB7cn0KIyMgR2V0IHRvdGFsIGRheXMgaW4gdGhlIHN0dWR5CnRvdGFsX2RheXNfaW5fc3R1ZHkgPSBhcy5udW1lcmljKGRpZmYuRGF0ZShjKG1pbihtb2xvX2RmJGRhdGUpLCBtYXgobW9sb19kZiRkYXRlKSkpKQoKIyMgQ3JlYXRlIGEgZGF0YWZyYW1lIHdoZXJlIHJvd3MgYXJlIHRhZyBpZCBhbmQgY29sdW1ucyBhcmUgc3R1ZHkgZGF0ZQpwcmVzZW50X2FmdGVyX25fZGF5c19kZiA9IGRhdGEuZnJhbWUoKQoKIyMgRGV0ZXJtaW5lIGlmIGEgdGFnIHdhcyBkZXRlY3RlZCBvbiBhIHJlY2VpdmVyIG4gZGF5cyBhZnRlciB0YWdnaW5nCmZvciAoaSBpbiAxOnVuaXF1ZU4obW9sb19kZiR0YWdfaWQpKXsKICAjIyBTdWJzZXQgZGF0YSBmb3IgaW5kaXZpZHVhbCB0YWdzCiAgaW5kdl9kYXRhID0gbW9sb19kZlttb2xvX2RmJHRhZ19pZCA9PSB1bmlxdWUobW9sb19kZiR0YWdfaWQpW2ldLCBdCiAgIyMgRGV0ZXJtaW5lIGlmIGEgZmlzaCB3YXMgcHJlc2VudCBuIGRheXMgYWZ0ZXIgdGFnZ2luZwogIGRpZmZ0aW1lcyA9IHJlcCgwLCBsZW4gPSB0b3RhbF9kYXlzX2luX3N0dWR5KQogICMgZGV0ZXJtaW5lIGRpZmZlcmVuY2UgaW4gZGF5cyBiZXR3ZWVuIGVhY2ggdW5pcXVlIGRheSBhIHRhZyB3YXMgZGV0ZWN0ZWQgYW5kIHRoZSB0YWcncyBlYXJsaWVzdCBkZXRlY3Rpb24sIGZsaXAgdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWUgaW4gZGlmZnRpbWVzIGFycmF5IHRvIDEKICBkZXRlY3RlZF9kYXRlcyA9IHVuaXF1ZShpbmR2X2RhdGEkZGF0ZSkKICBmb3IgKGogaW4gMTpsZW5ndGgoZGV0ZWN0ZWRfZGF0ZXMpKXsKICAgIGRpZmZ0aW1lc1thcy5udW1lcmljKGRpZmYuRGF0ZShjKG1pbihpbmR2X2RhdGEkZGF0ZSksIGRldGVjdGVkX2RhdGVzW2pdKSkpICsgMV0gPSAxCiAgfQogIGRmX3JvdyA9IGModW5pcXVlKG1vbG9fZGYkdGFnX2lkKVtpXSwgZGlmZnRpbWVzKQogIHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmID0gcmJpbmQocHJlc2VudF9hZnRlcl9uX2RheXNfZGYsIGRmX3JvdykKfQpjb2xuYW1lcyhwcmVzZW50X2FmdGVyX25fZGF5c19kZikgPSBjKCd0YWdfaWQnLCBhcy5jaGFyYWN0ZXIoMTp0b3RhbF9kYXlzX2luX3N0dWR5KSkKCiMjIENvbnZlcnQgZnJvbSB3aWRlIGZvcm1hdCB0byBsb25nIGZvcm1hdApwcmVzZW50X2FmdGVyX25fZGF5c19kZl9sb25nX2RmID0gbWVsdChwcmVzZW50X2FmdGVyX25fZGF5c19kZiwgaWQudmFycyA9ICd0YWdfaWQnLCBtZWFzdXJlLnZhcnMgPSBjb2xuYW1lcyhwcmVzZW50X2FmdGVyX25fZGF5c19kZilbMjpuY29sKHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmKV0sIHZhcmlhYmxlLm5hbWUgPSAnZGF5JywgdmFsdWUubmFtZSA9ICdkZXRlY3RlZCcpCgojIyBNZXJnZSB3aXRoIHNwZWNpZXMgZGF0YQpwcmVzZW50X2FmdGVyX25fZGF5c19kZl9sb25nX2RmID0gbWVyZ2UoeCA9IHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmX2xvbmcrZGYsIHkgPSB0YWdnaW5nX2RmWyAsYygndGFnX2lkJywgJ3NwZWNpZXMnKV0sIG9uID0gJ3RhZ19pZCcpCgojIyBDYWxjdWxhdGUgbnVtYmVyIG9mIGVhY2ggc3BlY2llcyBwcmVzZW50IG4gZGF5cyBhZnRlciB0YWdnaW5nCnNwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyA9IGFnZ3JlZ2F0ZShkZXRlY3RlZCB+IHNwZWNpZXMgKyBkYXksIGRhdGEgPSBwcmVzZW50X2FmdGVyX25fZGF5c19kZl9sb25nLCBGVU4gPSBzdW0pCiAgY29sbmFtZXMoc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nKSA9IGMoJ3NwZWNpZXMnLCAnZGF5JywgJ25faW5kaXZpZHVhbHMnKQoKIyMgQ291bnQgdW5pcXVlIHRhZ3MgYnkgc3BlY2llcwppbmRpdmlkdWFsc19wZXJfc3BlY2llcyA9IGFnZ3JlZ2F0ZSh0YWdfaWQgfiBzcGVjaWVzLCBkYXRhID0gcHJlc2VudF9hZnRlcl9uX2RheXNfZGZfbG9uZywgRlVOID0gdW5pcXVlTikKY29sbmFtZXMoaW5kaXZpZHVhbHNfcGVyX3NwZWNpZXMpID0gYygnc3BlY2llcycsICduX3RhZ3MnKQoKIyMgU3RhbmRhcmRpemUgc3BlY2llcyBsZXZlbCBkYWlseSBjb3VudHMgYnkgbnVtYmVyIG9mIHRhZ3MgYmVsb25naW5nIHRvIHRoYXQgc3BlY2llcwpzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmcgPSBtZXJnZSh4ID0gc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nLCB5ID0gaW5kaXZpZHVhbHNfcGVyX3NwZWNpZXMsIG9uID0gJ3NwZWNpZXMnKQpzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckcGVyY2VudF9pbmRpdmlkdWFsc19kZXRlY3RlZCA9IHNwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyRuX2luZGl2aWR1YWxzIC8gc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJG5fdGFncwoKIyMgQ2FsY3VsYXRlIDMwIGRheSBtb3ZpbmcgYXZlcmFnZQpzcHBfcHJlc2VuY2VfMzBfZGF5X2F2ZyA9IGRhdGEuZnJhbWUoKQpmb3IgKHNwZWNpZXMgaW4gc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJHNwZWNpZXMpewogIHNwcF9wcmVzZW5jZV9hZnRlcl90YWdnaW5nID0gc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nW3NwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyRzcGVjaWVzID09IHNwZWNpZXMsIF0KICBtb3ZpbmdfYXZlcmFnZV8zMCA9IGMoKQogIGZvciAoaSBpbiAzMDptYXgoc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJGRheXMpKXsKICAgIG1vdmluZ19hdmVyYWdlXzMwID0gYyhtb3ZpbmdfYXZlcmFnZV8zMCwgbWVhbihzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckcGVyY2VudF9pbmRpdmlkdWFsc19kZXRlY3RlZFtzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckZGF5ID49IGktMzAgJiBzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckZGF5IDw9IGldKSkKICB9CiAgZGZfcm93ID0gYyhzcGVjaWVzLCBtb3ZpbmdfYXZlcmFnZV8zMCkKICBzcHBfcHJlc2VuY2VfMzBfZGF5X2F2ZyA9IHJiaW5kKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnLCBkZl9yb3cpCn0KY29sbmFtZXMoc3BwX3ByZXNlbmNlXzMwX2RheV9hdmcpID0gYygnc3BlY2llcycsIGFzLmNoYXJhY3RlcigxOihuY29sKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnKS0xKSkpCgojIyBDb252ZXJ0IGZyb20gd2lkZSBmb3JtYXQgdG8gbG9uZyBmb3JtYXQKc3BwX3ByZXNlbmNlXzMwX2RheV9hdmdfbG9uZ19kZiA9IG1lbHQoc3BwX3ByZXNlbmNlXzMwX2RheV9hdmcsIGlkLnZhcnMgPSAnc3BlY2llcycsIG1lYXN1cmUudmFycyA9IGNvbG5hbWVzKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnKVsyOm5jb2woc3BwX3ByZXNlbmNlXzMwX2RheV9hdmcpXSwgdmFyaWFibGUubmFtZSA9ICdkYXknLCB2YWx1ZS5uYW1lID0gJ3BlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQnKQoKIyMgR2VuZXJhdGUgbGluZSBwbG90CnByZXNlbnRfYWZ0ZXJfdGFnZ2luZ19wbG90ID0gZ2dwbG90KHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnX2xvbmdfZGYsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgeSA9IHBlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQsIGNvbG9yID0gc3BlY2llcykpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHggPSAnTnVtYmVyIG9mIGRheXMnLCB5ID0gJ1Byb3BvcnRpb24gcHJlc2VudCcpICsKICBnZ3NhdmUoZmlsZW5hbWUgPSAnUHJvcG9ydGlvbiBvZiB0YWdzIHByZXNlbnQgYWZ0ZXIgdGFnZ2luZy5wZGYnLCBwYXRoID0gZmlndXJlX2RpcmVjdG9yeSkKCnByaW50KHByZXNlbnRfYWZ0ZXJfdGFnZ2luZ19wbG90KQpgYGAKCiMgU3RhdGlzdGljYWwgYW5hbHlzaXMKCkNhbGN1bGF0ZSBtZWFuIHJlc2lkZW5jeSBieSBzcHAgKGlycmVnYXJkbGVzcyBvZiB0aW1lKSwgdGhlbiBBTk9WQSBieSBzcHAKVXNlIFR1a2V5J3MgSFNEIHRvIGRldGVybWluZSBzaWduaWZpY2FuY2UKYGBge3J9CiMjIEFOT1ZBIG1vZGVsIGZvciByZXNpZGVuY3kgbWV0cmljIGJ5IHNwZWNpZXMKcmVzaWRlbmNlX2J5X3NwZWNpZXNfYW5vdmEgPSBhb3YocmVzaWRlbmNlX21ldHJpYyB+IHNwZWNpZXMsIGRhdGE9ZGV0ZWN0aW9uX3N0YXRzKQpzdW1tYXJ5KHJlc2lkZW5jZV9ieV9zcGVjaWVzX2Fub3ZhKQoKIyMgVHVrZXkncyBIb25lc3RseSBTaWduaWZpY2FudCBEaWZmZXJlbmNlcyBiZXR3ZWVuIHNwZWNpZXMKVHVrZXlIU0QocmVzaWRlbmNlX2J5X3NwZWNpZXNfYW5vdmEpCmBgYAoKR0xNIGNvbXBhcmluZyBzaXplIGFuZCByZXNpZGVuY3kgdGltZSBieSBzcHAgaW5kZXBlbmRlbnQgdmFyIChzaXplLCB0aW1lIGF0IGxpYmVydHkpIGRlcGVuZGVudCAocmVzaWRlbmN5IGluZGV4KQpgYGB7cn0KIyMgRml0IGJpbm9taWFsIEdMTSB0byBhdmVyYWdlIHJlc2lkZW5jeSBtZXRyaWMgZGF0YSAocHJvcG9ydGlvbmFsIGJldHdlZW4gMC0xKQpzcGVjaWVzX2dsbSA9IGdsbShyZXNpZGVuY2VfbWV0cmljIH4gIHNwZWNpZXMgKyBmb3JrX2xlbmd0aF9jbSAqZGF5c19hdF9saWJlcnR5ICogc3BlY2llcywgZGF0YSA9IGRldGVjdGlvbl9zdGF0cywgZmFtaWx5ID0gYmlub21pYWwobG9naXQpKQpzdW1tYXJ5KHNwZWNpZXNfZ2xtKQpgYGAKCiMjIEdMTSBjb21wYXJpbmcgdGltZSBpbiBjcmF0ZXIgdG8gdmVzc2VsIHRyYWZmaWMKYGBge3J9CgpgYGA=